﻿using MVCScaffolder.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MVCScaffolder
{
    public class ModelsCS
    {
        private SpaceStackStringBuilder sb = new SpaceStackStringBuilder();
        
        CodeGeneratorProperty CodeGeneratorProperties = null;

        public ModelsCS(CodeGeneratorProperty CodeGeneratorProperties)
        {
            sb = new SpaceStackStringBuilder();
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Collections.Generic;");
            sb.AppendLine("using System.Linq;");
            sb.AppendLine("using System.Web;");
            sb.AppendLine("using System.Web.Mvc;");
            sb.AppendLine("using System.ComponentModel.DataAnnotations;");
            sb.AppendLine();
            sb.AppendLine("namespace " + CodeGeneratorProperties.NamespaceName + ".Models");
            sb.AppendLine("{");
            if (true)
            {
                AddBaseModelClass();

                sb.AppendStart();
                sb.Append(Basics.GetClassDetailClassBaseClass(CodeGeneratorProperties.PropertyClassName, CodeGeneratorProperties.GridChoices, CodeGeneratorProperties.SelectedEntitySet));
                sb.AppendLine();

                AddClassIndexModel();

                if (CodeGeneratorProperties.GridChoices.Count > 0)
                {
                    sb.AppendLine();
                    sb.AppendLine("// Model Out to the browser when Editing");
                    sb.AppendLine("public class " + CodeGeneratorProperties.PropertyClassName + "CreateOrEdit : " + CodeGeneratorProperties.PropertyClassName + "Base");
                    sb.AppendLine("{");
                    if (true)
                    {
                        sb.AddSpace();
                        foreach (var item in CodeGeneratorProperties.GridChoices)
                        {
                            sb.AppendLine("public IEnumerable<SelectListItem> " + item.ColumnName + " { get; set; }");

                            String DataType = Basics.GetDataTypeFromTableNameColumnName(item.PrimaryTable, item.PrimaryKey, CodeGeneratorProperties.SelectedEntitySet);
                            sb.AppendStart();
                            sb.Append("public " + DataType);
                            if (item.CanLinkedTableBeNull)
                            {
                                if (DataType == "String")
                                {
                                    // do nothing
                                }
                                else
                                {
                                    sb.Append("?");
                                }
                            }
                            sb.Append(" DDL" + item.ColumnName + " { get; set; }");

                            sb.AppendLine();
                        }
                        sb.RemoveSpace();
                    }
                    sb.AppendLine("}");
                }
                sb.AppendLine();
                sb.RemoveSpace();
            }
            sb.AppendLine("}");
        }

        private void AddClassIndexModel()
        {
            sb.AppendLine();
            sb.AppendLine("// Model for the Index page.");
            sb.AppendLine("public class " + CodeGeneratorProperties.PropertyClassName + "Index : BasicIndexPage");
            sb.AppendLine("{");
            if (true)
            {
                sb.AddSpace();

                foreach (Searchable item in CodeGeneratorProperties.SearchChoices)
                {
                    bool UsingDDL = false;
                    foreach (var GridChoice in CodeGeneratorProperties.GridChoices)
                    {
                        if (item.ColumnName == GridChoice.ColumnName)
                        {
                            sb.AppendLine();
                            sb.AppendLine("public String " + item.Property.Name + "Search { get; set; }");
                            sb.AppendLine();
                            sb.AppendLine(@"[Display( Name=""" + item.Property.Name.MakeFriendlyDisplayField() + @""")]");
                            sb.AppendLine("public IEnumerable<SelectListItem> " + item.Property.Name + "SearchOption { get; set; }");
                            UsingDDL = true;
                        }
                    }
                    if (UsingDDL == false)
                    {
                       
                        if (item.Property.Type.Contains("DateTime"))
                        {
                            sb.AppendLine();
                            sb.AppendLine("public String " + item.Property.Name + "SearchOptionResult { get; set; }");
                            sb.AppendLine();
                            sb.AppendLine(@"[Display( Name=""" + item.Property.Name.MakeFriendlyDisplayField() + @""")]");
                            sb.AppendLine("public IEnumerable<SelectListItem> " + item.Property.Name + "SearchOption { get; set; }");
                            sb.AppendLine("public DateTime? " + item.Property.Name + "Search { get; set;}");
                            sb.AppendLine("public DateTime? " + item.Property.Name + "SearchBetween { get; set; }");
                        }
                        else if (item.Property.Type.Contains("Boolean"))
                        {
                            sb.AppendLine();
                            sb.AppendLine("public String " + item.Property.Name + "Search { get; set; }");
                            sb.AppendLine();
                            sb.AppendLine(@"[Display( Name=""" + item.Property.Name.MakeFriendlyDisplayField() + @""")]");
                            sb.AppendLine("public IEnumerable<SelectListItem> " + item.Property.Name + "SearchOption { get; set; }");
                        }
                        else if (item.Property.Type.Contains("Int64"))
                        {
                            sb.AppendLine();
                            sb.AppendLine("public String " + item.Property.Name + "SearchOptionResult { get; set; }");
                            sb.AppendLine();
                            sb.AppendLine(@"[Display( Name=""" + item.Property.Name.MakeFriendlyDisplayField() + @""")]");
                            sb.AppendLine("public IEnumerable<SelectListItem> " + item.Property.Name + "SearchOption { get; set; }");
                            sb.AppendLine("public Int64? " + item.Property.Name + "Search { get; set;}");
                            sb.AppendLine("public Int64? " + item.Property.Name + "SearchBetween { get; set; }");
                        }
                        else if (item.Property.Type.Contains("Int32"))
                        {
                            sb.AppendLine();
                            sb.AppendLine("public String " + item.Property.Name + "SearchOptionResult { get; set; }");
                            sb.AppendLine();
                            sb.AppendLine(@"[Display( Name=""" + item.Property.Name.MakeFriendlyDisplayField() + @""")]");
                            sb.AppendLine("public IEnumerable<SelectListItem> " + item.Property.Name + "SearchOption { get; set; }");
                            sb.AppendLine("public int? " + item.Property.Name + "Search { get; set;}");
                            sb.AppendLine("public int? " + item.Property.Name + "SearchBetween { get; set; }");
                        }
                        else if (item.Property.Type.Contains("Int16"))
                        {
                            sb.AppendLine();
                            sb.AppendLine("public String " + item.Property.Name + "SearchOptionResult { get; set; }");
                            sb.AppendLine();
                            sb.AppendLine(@"[Display( Name=""" + item.Property.Name.MakeFriendlyDisplayField() + @""")]");
                            sb.AppendLine("public IEnumerable<SelectListItem> " + item.Property.Name + "SearchOption { get; set; }");
                            sb.AppendLine("public int? " + item.Property.Name + "Search { get; set;}");
                            sb.AppendLine("public int? " + item.Property.Name + "SearchBetween { get; set; }");
                        }
                        else if (item.Property.Type.Contains("Decimal"))
                        {
                            sb.AppendLine();
                            sb.AppendLine("public String " + item.Property.Name + "SearchOptionResult { get; set; }");
                            sb.AppendLine();
                            sb.AppendLine(@"[Display (Name=""" + item.Property.Name.MakeFriendlyDisplayField() + @""")]");
                            sb.AppendLine("public IEnumerable<SelectListItem> " + item.Property.Name + "SearchOption { get; set; }");
                            sb.AppendLine("public Decimal? " + item.Property.Name + "Search { get; set;}");
                            sb.AppendLine("public Decimal? " + item.Property.Name + "SearchBetween { get; set; }");
                        }
                        else if (item.Property.Type.Contains("Single"))
                        {
                            sb.AppendLine();
                            sb.AppendLine("public String " + item.Property.Name + "SearchOptionResult { get; set; }");
                            sb.AppendLine();
                            sb.AppendLine(@"[Display( Name=""" + item.Property.Name.MakeFriendlyDisplayField() + @""")]");
                            sb.AppendLine("public IEnumerable<SelectListItem> " + item.Property.Name + "SearchOption { get; set; }");
                            sb.AppendLine("public short? " + item.Property.Name + "Search { get; set;}");
                            sb.AppendLine("public short? " + item.Property.Name + "SearchBetween { get; set; }");
                        }
                        else
                        {
                            sb.AppendLine();
                            sb.AppendLine(@"[Display( Name=""" + item.Property.Name.MakeFriendlyDisplayField() + @""")]");
                            sb.AppendLine("public String " + item.Property.Name + "Search { get; set;}");
                        }
                    }
                }

                sb.AppendLine();
                sb.AppendLine("public IEnumerable<" + CodeGeneratorProperties.PropertyClassName + "Detail> " + CodeGeneratorProperties.PropertyClassName + "Details { get; set; }");

                sb.RemoveSpace();
            }
            sb.AppendLine("}");
        }

        private void AddBaseModelClass()
        {
            sb.AddSpace();
            sb.AppendLine("// Base class ");
            sb.AppendLine("public class " + CodeGeneratorProperties.PropertyClassName + "Base");
            sb.AppendLine("{");
            if (true)
            {
                sb.AddSpace();

                foreach (EDMXParserV1.Property Item in CodeGeneratorProperties.SelectedEntitySet.EntityTypeLink.Properties)
                {

                    bool GridChoiceFound = false;
                    foreach (GridChoice GridChoice in CodeGeneratorProperties.GridChoices)
                    {
                        if (GridChoice.ColumnName == Item.Name)
                        {
                            GridChoiceFound = true;
                            break;
                        }
                    }

                    if (GridChoiceFound == false)
                    {
                        bool AddingRequired = false;
                        if (Item.IsNullable())
                        {

                        }
                        else
                        {
                            sb.AppendLine("[Required]");
                            if (Item.Type == "String")
                            {

                                AddingRequired = true;
                            }
                            else
                            {


                            }
                        }
                        String Line = "public " + Item.Type;
                        if (AddingRequired)
                        {
                            // do nothing
                        }
                        else
                        {
                            if (Item.IsNullable())
                            {
                                if (Item.Type == "String")
                                {
                                    // do nothing
                                    // apparently you can't nullable on a String
                                }
                                else
                                {
                                    Line = Line + "?";
                                }
                            }
                            else
                            {

                            }
                        }

                        Line = Line + " " + Item.Name + " { get; set; }";
                        sb.AppendLine(Line);
                        sb.AppendLine();
                    }
                }
                sb.RemoveSpace();
            }
            sb.AppendLine("}");
        }

        public override string ToString()
        {
            return sb.ToString();
        }
    }
}
